// ==UserScript==
// @name      递归获取页面元素内容
// @namespace  http://apz.homepage.com/
// @version    1.0.0
// @description  递归获取页面元素内容
// @copyright  2023+, You
// @author       You
// @match      *://*/*/darkanddarker.wiki.spellsandguns.com/*
// @icon         images/txt.png
// @require      /js/jquery-3.4.1.js
// @require      /js/jszip.min.js
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_addStyle
// @grant       GM_xmlhttpRequest
// @connect     127.0.0.1
// @grant       GM_setValueFromScript
// @grant       GM_sendMsgToScript 
// @grant       GM_registerMsgListener
// @downloadURL	http://127.0.0.1:8085/userScript/递归获取页面元素内容.js
// ==/UserScript==
// @downloadURL:用户脚本更新地址
// @include：@include 指令用于指定匹配网址的规则。你可以使用通配符 * 匹配部分 URL，或使用正则表达式来匹配特定的页面。
// 例如，@include https://example.com/* 将匹配以 "https://example.com/" 开头的所有网址，而 @include /^https?:\/\/(www\.)?example\.com/ 
// 将匹配所有以 "https://" 或 "http://" 开头、以 "example.com" 结尾的网址。
// @match：@match 指令也用于指定匹配网址的规则，它支持更丰富的匹配模式。@match 使用通配符语法来匹配 URL，其中 * 可以匹配任意字符（除了 /），** 可以匹配任意字符（包括 /）。
//例如，@match https://example.com/* 和 @match *://example.com/* 都将匹配以 "https://example.com/" 开头的所有网址。
//@match https://**.example.com/* 将匹配以 "https://" 开头，以 ".example.com/" 结尾的所有网址。
//https://api.cponline.cnipa.gov.cn/zljffw/fycx/yjfywbl/listyjf-batchhdpage,{zhuanlisqhs: ["2017106745492"], size: 10, current: 1}
(function () {
    // 需要查询的专利列表
    let patentBuyList = [{ patentid: '2019110050048' }, { patentid: '2014107234471' }, { patentid: '2021114837007' }];
    // let patentBuyList = [];
    let page = 1;
    let limit = 10;
    const uploadUrl = "https://127.0.0.1/api/Aborablemonkey/htmlUpload"
    const tmValue = 1000

    Date.prototype.format = function (fmt) {
        var o = {
            "M+": this.getMonth() + 1,                 //月份
            "d+": this.getDate(),                    //日
            "h+": this.getHours(),                   //小时
            "m+": this.getMinutes(),                 //分
            "s+": this.getSeconds(),                 //秒
            "q+": Math.floor((this.getMonth() + 3) / 3), //季度
            "S": this.getMilliseconds()             //毫秒
        };
        if (/(y+)/.test(fmt)) {
            fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
        }
        for (var k in o) {
            if (new RegExp("(" + k + ")").test(fmt)) {
                fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
            }
        }
        return fmt;
    };
    const initInputDomProto = () => {
        let input = document.querySelector('input');
        let descriper = Object.getOwnPropertyDescriptor(input.__proto__, 'value');
        //取出原先的get和set函数
        let getValue = descriper.get;
        let setValue = descriper.set;
        Object.defineProperty(
            input.__proto__,
            'value',
            {
                configurable: true,
                enumerable: true,
                get: function () {
                    return getValue.call(this);
                },
                // 重写set方法
                set: function () {
                    //console.log('value发生变化',arguments);
                    // 加入通知代码
                    setValue.call(this, ...arguments);
                    //this.focus()
                    this.dispatchEvent(new InputEvent("input"))
                    // this.dispatchEvent(new InputEvent("change"))
                    //this.blur()
                }
            })
    }

    const htmlUpload = (htmlCont, htmlFileName) => {
        // debugger
        let jsonData = "file=" + "base64" + "&fileName=" + "htmlFileName";
        if (!('TextEncoder' in window)) {
            // 使用TextEncoder API将字符串编码为Uint8Array
            let encoder = new TextEncoder('utf-8');
            // let encoder = new TextEncoder('windows-1252');

            let data = encoder.encode(htmlCont);
            let base64 = btoa(String.fromCharCode.apply(null, data));
            //  base64 = atob(base64);
            jsonData = "file=" + base64 + "&fileName=" + htmlFileName;
        } else {
            // 如果浏览器不支持TextEncoder，则使用unescape()和encodeURIComponent()函数进行编码
            let data = encodeURIComponent(htmlCont);
            // let base64 = btoa(data);
            jsonData = "file=" + data + "&fileName=" + htmlFileName;
        }


        GM_xmlhttpRequest({
            url: uploadUrl,
            method: "POST",
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' // 设置编码格式为 UTF-8
            },
            data: jsonData,
            onload: function (response) {
                const ret = JSON.parse(response.responseText)
                alert('提交完成，文件已覆盖，刷新即可！！！');
                if (ret.code == 1) {
                    console.log("请求成功:", ret.data)
                    feeDeail = ret.data
                }
            },
            onerror: function (response) {
                console.log("请求失败", response)
            }
        })
    }
    let cnt = 10;
    let idx = 0;
    let step = 0;
    const performStep4 = () => {
        //取出所有包含a的控件
        let domList = $('body')[0].getElementsByTagName('li');
        let filteredDomList = Array.from(domList).filter(element => {
            const aElement = element.querySelector('a');
            return (aElement);
        });
        //不包含a下面的span和p
        filteredDomList = Array.from(filteredDomList).filter(element => {
            const aElement = element.querySelector('span');
            const pElement = element.querySelector('p');
            return (!aElement && !pElement);
        });

        idx = 0;
        step++;
        console.log('准备翻译条目4：', filteredDomList.length);
        performTranslate(filteredDomList);
    }

    const performStep3 = () => {
        //取出所有不包含p，span，a的控件
        let domList = $('body')[0].getElementsByTagName('li');
        const filteredDomList = Array.from(domList).filter(element => {
            const pElement = element.querySelector('p');
            const spanElement = element.querySelector('span');
            const aElement = element.querySelector('a');
            return (!pElement && !spanElement && !aElement);
        });
        idx = 0;
        step++;
        console.log('准备翻译条目3：', filteredDomList.length);
        performTranslate(filteredDomList);
    }
    const performTranslate = (emtS) => {
        if (idx >= emtS.length) {
            console.log('错误，越界->idx:', idx);
            // // 网站翻译完成，提交网页内容
            // let htmlCnt = $('html');
            // // 替换的文件名
            // let pathWeb = window.location.pathname;
            // htmlUpload(htmlCnt, pathWeb);
            if (step == 1) {
                performStep3();
            }
            //  else if (step == 2) {
            //     performStep4();                        
            // } 
            else {
                alert('翻译完成，检查后提交页面保存！！！');
            }
            return
        }

        if (typeof emtS[idx] == 'undefined') {

            console.log('对象不存在:emtS[%d]:', idx);
            idx++;
            performTranslate(emtS);
        }
        console.log('--->', emtS[idx], "->idx:", idx);
        let sendValue = emtS[idx].innerText;
        if (isNaN(sendValue.trim())) {
            console.log('准备翻译:', emtS[idx].innerText);
            GM_sendMsgToScript({ msg: { cmd: "翻译字串", value: sendValue } }, ['*://fanyi.baidu.com/*']).then((ret) => {
                console.log('收到翻译结果:', ret[0].msg.result);
                // debugger
                emtS[idx].innerHTML = ret[0].msg.result
                idx++;
                if (idx >= emtS.length) {
                    if (step == 0) {
                        idx = 0;
                        step++;
                        let lemt = $('body')[0].getElementsByTagName('p');
                        console.log('准备翻译条目2：', lemt.length);
                        performTranslate(lemt);
                    } else if (step == 1) {
                        performStep3();
                    }
                    // else if (step == 2) {
                    //     performStep4();                        
                    // }
                    else {
                        alert('翻译完成，检查后提交页面保存！！！');
                    }
                    return
                }
                performTranslate(emtS);

                // //////////////////////////////////////////////////////////////////////////////////////////////
                // // 网站翻译完成，提交网页内容
                // let htmlCnt = $('html');
                // // 替换的文件名
                // let pathWeb = window.location.pathname;
                // htmlUpload(htmlCnt, pathWeb);
                // //////////////////////////////////////////////////////////////////////////////////////////////
            }).catch((err) => {
                console.log('收到错误返回:', err);
                idx = 0;
            });
        } else {
            console.log('翻译内容为空:', idx);
            idx++;
            performTranslate(emtS);
        }
    }



    const performDOMRecursion = (ele) => {
        for (let idx = 0; idx < ele.length; idx++) {

            if (ele[idx].childNodes.length > 0) {
                performDOMRecursion(ele[idx].childNodes);
            } else {
                let v = ele[idx].nodeValue && ele[idx].nodeValue.trim();
                if (v != '') {
                    console.log('-->', ele[idx], '--->', v);
                }
            }
        }
    }
    let countEle = 0;
    function printLeafControlContent(element) {
        // 如果当前元素没有子节点，即为叶子控件，打印其内容
        if (!element.hasChildNodes()) {
            let v = element.textContent.trim();
            const regex = /^[^,.|\/≡|\||页面翻译操作|根据需要点击对应按钮|关闭|\"|-]*$/;
            if (v !== '' && isNaN(v) && regex.test(v)) {
                countEle++;
                if (element.parentElement.nodeName !== 'SCRIPT' && element.parentElement.nodeName !== 'STYLE') {
                    console.log(element.parentElement.nodeName, 'nodetype:', element.nodeType, '----', v);
                }
            }
        } else {
            // 遍历当前元素的子节点
            const childNodes = element.childNodes;
            for (let i = 0; i < childNodes.length; i++) {
                const childNode = childNodes[i];
                // 只处理元素节点
                // debugger
                if (element.parentElement.nodeName !== 'STYLE' && element.parentElement.nodeName !== 'SCRIPT') {
                    printLeafControlContent(childNode);
                }
            }
        }
    }
    // 示例使用回调函数打印节点名称
    function printNodeName(node) {

        let v = node.textContent.trim();
        // 'Flying type, spits 6 poisons globs in a fan-like motion that inflict poison upon direct impact. \n\n\nNightmare: Now spits 10 projectiles.'
        //const regex = /^[^,|≡|\||页面翻译操作|根据需要点击对应按钮|关闭|\"|-]*$/;
        const regex = /^[^,|≡|\||页面翻译操作|根据需要点击对应按钮|关闭|\"|^-]*$/;
        if (v !== '' && isNaN(v) && regex.test(v)) {
            if (node.parentElement.nodeName !== 'SCRIPT' && node.parentElement.nodeName !== 'STYLE') {
                countEle++;
                console.log(node.parentElement.nodeName, 'nodetype:', node.nodeType, '----', v, '->', node);
                node.nodeValue = '111';
            }
        } else if(/(-.*%)/g.test(v)){
            if (node.parentElement.nodeName !== 'SCRIPT' && node.parentElement.nodeName !== 'STYLE') {
                countEle++;
                console.log(node.parentElement.nodeName, 'nodetype:', node.nodeType, '----', v, '->', node);
                node.nodeValue = '111';
            }
        }
        // console.log(node.nodeName);
    }
    // 示例使用回调函数打印节点名称
    function printNodeName2(node) {

        let v = node.textContent.trim();
        // 'Flying type, spits 6 poisons globs in a fan-like motion that inflict poison upon direct impact. \n\n\nNightmare: Now spits 10 projectiles.'
        const regex = /^[^,|≡|\||页面翻译操作|根据需要点击对应按钮|关闭|\"|-]*$/;
        // if (v !== '' && isNaN(v) && regex.test(v)) {
        if (v !== '' && isNaN(v)) {
            countEle++;
            if (node.parentElement.nodeName !== 'SCRIPT' && node.parentElement.nodeName !== 'STYLE') {
                console.log(node.parentElement.nodeName, 'nodetype:', node.nodeType, '----', v, '->', node);
                node.innerText = '111';
            }
        }
        // console.log(node.nodeName);
    }
    // 不使用循环语句遍历节点      
    function traverseDOM(node, callback) {
        if (node.childNodes.length === 0) {
            callback(node);
        } else if (node.nodeName == 'P') {
            // printNodeName2(node);
        } else {
            let child = node.firstChild;
            while (child) {
                traverseDOM(child, callback);
                child = child.nextSibling;
            }
        }
    }
    const performAsyncTranslate= async (node, callback) =>{
        if (node.childNodes.length === 0) {
            callback(node);
        } else if (node.nodeName == 'P') {
            printNodeName2(node);
        } else {
            let child = node.firstChild;
            while (child) {
                traverseDOM(child, callback);
                child = child.nextSibling;
            }
        }
    }

    const run = function () {
        cnt++;
        // let emt = $('body')[0].getElementsByTagName('span');
        // performTranslate(emt);
        let emt = $('body')[0].getElementsByTagName('li');
        if (emt) {
            console.log('准备执行：', emt.length)
            // performDOMRecursion(emt);
            // 使用 document.body 作为根元素开始递归遍历
            // printLeafControlContent(document.body);
            traverseDOM(document.body, printNodeName);
            console.log('执行结束：', countEle);
            return true;
        } else {
            return false;
        }
    }

    // 添加样式
    GM_addStyle(`
      /* 定义悬浮框的样式 */
      .floating-box-apz {
          position: fixed;
          top: 10%;
          left: 80%;
          transform = 'translate(-50%, -50%)';
          background-color: #220ef2;
          border: 1px solid #ccc;
          box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
          padding: 10px;
          text-align: center;
          z-index: 9999;
        }
      /* 定义按钮的样式 */
      .floating-box-apz button {
          margin: 5px;
        }
      /* 定义按钮的样式 */
      .floating-box-apz label {
        color: #f2fef2;
        }  
      `);
    // 显示翻译按钮
    const showRunButton = () => {
        // 创建悬浮框元素
        var floatingBox = document.createElement('div');
        floatingBox.className = 'floating-box-apz';
        floatingBox.innerHTML = `
        <h3>页面翻译操作</h3>
        <label>根据需要点击对应按钮</label>
        <p></p>
        <button id="startBtn">启动翻译</button>
        <button id="submitBtn">提交页面</button>
        <button id="closeBtn">关闭</button>
        `;

        // 将悬浮框添加到页面中
        document.body.appendChild(floatingBox);

        // 鼠标拖动事件处理函数
        let drag = false; // 标记是否正在拖动
        let offsetX, offsetY;

        // 鼠标按下事件
        floatingBox.addEventListener('mousedown', function (e) {
            drag = true;
            offsetX = e.clientX - floatingBox.offsetLeft;
            offsetY = e.clientY - floatingBox.offsetTop;
        });

        // 鼠标移动事件
        document.addEventListener('mousemove', function (e) {
            if (drag) {
                floatingBox.style.left = (e.clientX - offsetX) + 'px';
                floatingBox.style.top = (e.clientY - offsetY) + 'px';
            }
        });

        // 鼠标释放事件
        document.addEventListener('mouseup', function () {
            drag = false;
        });

        // 启动按钮点击事件处理函数
        const startBtn = document.getElementById('startBtn');
        startBtn.addEventListener('click', function () {
            // alert('启动按钮被点击！');
            let tt = setInterval(function () {
                if (run()) {
                    clearInterval(tt)
                }
            }, tmValue);
        });

        // 提交按钮点击事件处理函数
        const submitBtn = document.getElementById('submitBtn');
        submitBtn.addEventListener('click', function () {
            // alert('提交按钮被点击！');
            const removeFloatBox = () => {
                //移除浮动框
                // 获取document.documentElement的outerHTML字符串
                let htmlString = document.documentElement.outerHTML;
                // 定义要删除的内容
                let targetString = '<div class="floating-box-apz"';
                // 使用正则表达式替换内容为空字符串
                let regexPattern = new RegExp(targetString + '.+?</div>', 's');
                let ret = htmlString.match(regexPattern);
                let modifiedHtmlString = htmlString.replace(ret[0], '');
                return modifiedHtmlString
            }
            // 网站翻译完成，提交网页内容
            floatingBox.style.display = 'none';
            // 替换的文件名
            let pathWeb = window.location.pathname;
            htmlUpload(removeFloatBox(), pathWeb);
            floatingBox.style.display = 'block';
        });
        const closeBtn = document.getElementById('closeBtn');
        closeBtn.onclick = function () {
            floatingBox.style.display = 'none';
        };
    }
    // debugger
    showRunButton();


    // GM_registerMsgListener((message, sender, sendResponse) => {
    //     console.log("User1收到消息:", message);
    //     sendResponse({ ret: 0, msg: 'User1已收到回复ACK...' + message.msg.value });
    // });
    // chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    //     console.log("跨域User1收到消息:", message);
    //     sendResponse('跨域User1已收到回复...');
    // });
})()